#include "calendar.h"
#include "ui_calendar.h"
#include "qmessagebox.h"
#include <QTextCharFormat>
#include <QMouseEvent>
#include <QColor>
#include <QLabel>
#include <QPlainTextEdit>
#include "global.h"
Calendar::Calendar(QWidget *parent)
    :QWidget(parent),
      ui(new Ui::Calendar)
{
    ui->setupUi(this);
    changed = false;
    toDoListPackage = new ToDoListPackage; //creat the packge of todolist
    changedRecord = new QList<ChangedRecord>;
    toDoListForm = new QList<ToDoListForm>;
    ToDoDateFormat = new QTextCharFormat ;
    todoListDates = new QList<QDate>;
    ToDoDateFormat->setFontWeight(QFont::Bold);
    ToDoDateFormat->setFontUnderline(true);
    //ToDoDateFormat->setUnderlineColor(QColor(255,0,255));
    ToDoDateFormat->setBackground(QBrush(QColor(255,0,255)));


    ////////////////////////////////////////////
    /*initialize the todolist table*/
    /////////////////////////////////////////////
    toDolistTable();

    /****************************************
      test data
      **************************************/
    //the first day
    ToDoListRecord record1 = {1,"i am hungry1"};
    ToDoListRecord record2 = {2,"i am hungry2"};
    QList<ToDoListRecord> recordDay1;
    recordDay1.push_back(record1);
    recordDay1.push_back(record2);
    ToDoListOfDay Day1 = {QDate::currentDate().addDays(1),recordDay1};
    toDoListPackage->toDoListContent.push_back(Day1);

    //the second day
    ToDoListRecord record3 = {1,"i am hungry3"};
    ToDoListRecord record4 = {2,"i am hungry4"};
    QList<ToDoListRecord> recordDay2;
    recordDay2.push_back(record3);
    recordDay2.push_back(record4);
    ToDoListOfDay Day2 = {QDate::currentDate().addDays(3),recordDay2};
    toDoListPackage->toDoListContent.push_back(Day2);

//   the third day
    ToDoListRecord record5 = {1,"i am hungry5"};
    ToDoListRecord record6 = {2,"i am hungry6"};
    QList<ToDoListRecord> recordDay3;
    recordDay3.push_back(record5);
    recordDay3.push_back(record6);
    ToDoListOfDay Day3 = {QDate::currentDate().addDays(7),recordDay3};
    toDoListPackage->toDoListContent.push_back(Day3);




    todoListDates->push_back(QDate::currentDate().addDays(1));
    todoListDates->push_back(QDate::currentDate().addDays(3));
    todoListDates->push_back(QDate::currentDate().addDays(7));
    //ModifyToDoListInPackage(QDate::currentDate().addDays(3),1,"i am hungry33");
    // RemoveToListFromPackage(QDate::currentDate().addDays(3),1);
    //addToDoListToPackage(QDate::currentDate().addDays(3),2,"i am hungry33");
    /******************************************/
    refresh();

//    QByteArray array = PackageToByteArray(toDoListPackage);
//    QMessageBox::information(NULL,"aa",array);

//    toDoListPackage = ByteArrayToPackage(array);



}


Calendar::~Calendar()
{
    delete ui;
}


////////////////////////////////////////////////////////////////
/*
  tableWidget fuctions
  */
///////////////////////////////////////////////////////////////////
void Calendar::toDolistTable()
{
    ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<tr("index")<<tr("content"));
   // ui->tableWidget

}
void Calendar::addRow()
{
    int row = ui->tableWidget->rowCount();

    ui->tableWidget->insertRow(row);
}
void Calendar::removeAll()
{
    //remove all the todolist in one day,
    //prepare to show another days todolist
    int rows = ui->tableWidget->rowCount();
    while(rows>0)
    {
        ui->tableWidget->removeRow(--rows);
    }
}
void Calendar ::showToDoRecord(int index, QString content)
{

       addRow();
       int row = ui->tableWidget->rowCount();
       QTableWidgetItem* indexItem = new QTableWidgetItem();
       indexItem->setFlags(Qt::ItemIsUserCheckable);
       indexItem->setText(QString::number(index));
       QTableWidgetItem* contentItem = new QTableWidgetItem();
       contentItem->setText(content);
       ui->tableWidget->setItem(row - 1,0,indexItem);
       ui->tableWidget->setItem(row - 1,1,contentItem);
}


/**************************************************************
  // package Fucntions include add and modify remove
  //
 ***********************************************************************/
 void Calendar::addToDoListToPackage(QDate const date,int const index, QString const content)
 {
     ToDoListRecord addRecord= {index,content};
     //if the date already has some todolist
     if(todoListDates->contains(date))
     {
         int records = toDoListPackage->toDoListContent.size();
         while(records > 0)
         {
             if(toDoListPackage->toDoListContent.at(records -1).date == date)
             {
                 QList<ToDoListRecord> recordDay = toDoListPackage->toDoListContent.at(records -1).toDoListRecord;
                 recordDay.push_back(addRecord);
                 ToDoListOfDay  temptodoListDay = {date,recordDay };
                 toDoListPackage->toDoListContent.replace(records -1, temptodoListDay);
                 //end loop when found and proccessed
                 break;
             }
             records --;
         }
     }
     ////if the date already has some todolist
     //add a new package item to package
     else
     {
         todoListDates->push_back(date);
         QList<ToDoListRecord> recordDay;
         recordDay.push_back(addRecord);
         ToDoListOfDay addDay={date,recordDay};
         toDoListPackage->toDoListContent.push_back(addDay);
         setDateTextFormat(date,ToDoDateFormat);

     }

 }
 void Calendar::ModifyToDoListInPackage(QDate const date,int const index, QString const newContent)
 {
     int records = toDoListPackage->toDoListContent.size();
     while(records > 0)
     {

         if(toDoListPackage->toDoListContent.at(records -1).date == date)
         {

             QList<ToDoListRecord> recordDay = toDoListPackage->toDoListContent.at(records -1).toDoListRecord;
             int tmpIndex = recordDay.size();
             for(int i = 0; i<tmpIndex; i++)
             {
               //when found, show the recordlist dynamically as the index
               if(i == index)
               {
                   //set newcontent
                   ToDoListRecord tmp = {index, newContent};
                   recordDay.replace(index, tmp);
                   //reconstruct the ToDoListOfDay due to the at function is const
                   //we cant modify directly throuhg at funtion
                   ToDoListOfDay  temptodoListDay = {date,recordDay };
                   toDoListPackage->toDoListContent.replace(records -1, temptodoListDay);
                   return;
               }

             }
         }
         records --;
     }
 }
 void Calendar::RemoveToListFromPackage(QDate const date,int const index)
 {
     int records = toDoListPackage->toDoListContent.size();
     while(records > 0)
     {

         if(toDoListPackage->toDoListContent.at(records -1).date == date)
         {
             QList<ToDoListRecord> recordDay = toDoListPackage->toDoListContent.at(records -1).toDoListRecord;
             int tmpIndex = recordDay.size();

             for(int i = 0; i<tmpIndex; i++)
             {
               //when found, show the recordlist dynamically as the index
               if(i == index)
               {
                   //set newcontent
                    recordDay.removeAt(i);
                    ToDoListOfDay  temptodoListDay = {date,recordDay };
                    toDoListPackage->toDoListContent.replace(records -1, temptodoListDay);
                    //if record is 1, there should be no record when delete
                    if(tmpIndex == 1)
                    {
                        todoListDates->removeOne(date);
                    }
                    return;
               }

             }
         }
         records --;
     }
 }



 /**************************************************************
   // button click slot
   //
  ***********************************************************************/
void Calendar::on_refreshButton_clicked()
{
    refresh();
}
void Calendar::on_addButton_clicked()
{
    changed = true;
    addRow();
    //set the default todoList
    int currentRow = ui->tableWidget->rowCount() - 1;
    QTableWidgetItem* indexItem = new QTableWidgetItem();
    //the index is readonly by users
    indexItem->setFlags(Qt::ItemIsUserCheckable);
    indexItem->setText(QString::number(currentRow));

    QTableWidgetItem* contentItem = new QTableWidgetItem();
    contentItem->setText("NULL");

    ui->tableWidget->setItem(currentRow,0,indexItem);
    ui->tableWidget->setItem(currentRow,1,contentItem);

    QDate date = ui->calendarWidget->selectedDate();
    //add to package
    addToDoListToPackage(date,currentRow,"");
}
void Calendar::on_deleteButton_clicked()
{
     changed = true;
    int row = ui->tableWidget->currentRow();
    QDate date = ui->calendarWidget->selectedDate();
    //remove from package
    RemoveToListFromPackage(date,row);
    if(row>=0)
    {

         QMessageBox * deleteMessage= new QMessageBox;
         deleteMessage->setText("you may not roll back after you delete\n are you sure?");
         deleteMessage->setStandardButtons(QMessageBox::Yes|QMessageBox::No);
         deleteMessage->setDefaultButton(QMessageBox::No);
         int clickButton = deleteMessage->exec();
         switch(clickButton)
         {
              case QMessageBox::Yes:
                 ui->tableWidget->removeRow(row);
              break;
              case QMessageBox::No:
              break;

         }
    }

}
void Calendar::processPackageResponse(MSGHeader header,QByteArray data)
{
    *toDoListPackage = ByteArrayToPackage(data);
    refresh();
}
void Calendar::on_saveButton_clicked()
{
    saveChanges();
}
void Calendar::saveChanges()
{
    if(changed == true)
    {
         MSGHeader * ToDoListHeader = new MSGHeader;
         int size = toDoListPackage->toDoListContent.size();
         ///fill a protocol MSGHeader
         constructHeader(*ToDoListHeader,UPDATE,TODOLIST,size,0,0);
         ///input the protocol and data,the put them together and return the package
         QByteArray arrayPackage = generatePackage( *ToDoListHeader, PackageToByteArray(toDoListPackage));
         emit sendPackageRequest(arrayPackage);
    }
}
void Calendar::refresh()
{
    int records = toDoListPackage->toDoListContent.size();
    while(records > 0)
    {
       QDate recordDate = toDoListPackage->toDoListContent.at(records -1).date;
       setDateTextFormat(recordDate,ToDoDateFormat);
       records --;
    }
}


/*
 when click the date, the recordlist will be shown if there are
any todolist on the date
*/

void Calendar::on_calendarWidget_clicked(QDate date)
{

    //removeAll todolist shown in the table before showing other days'
    removeAll();

    int records = toDoListPackage->toDoListContent.size();
    //find if the date has a todolist
     //do something to avoid unneccessay loop
    if(!todoListDates->contains(date))
        return ;
    //loop to find the the recordList of the date
    while(records > 0)
    {
        if(toDoListPackage->toDoListContent.at(records -1).date == date)
        {
            QList<ToDoListRecord> recordDay = toDoListPackage->toDoListContent.at(records -1).toDoListRecord;
            int index = recordDay.size();
            for(int i = 0; i<index; i++)
            {
              //when found, show the recordlist dynamically as the index
              showToDoRecord(i,recordDay.at(i).content);

            }
            //end loop when found and proccessed
            break;
        }
        records --;
    }

}


/**************************************************************
  // other view effect
  //
 ***********************************************************************/
void Calendar::setDateTextFormat(QDate date, QTextCharFormat *Format)
{
  ui->calendarWidget->setDateTextFormat(date,*Format);

}

void Calendar::on_tableWidget_itemChanged(QTableWidgetItem* item)
{
    //if the changed ocurs in initialization , do nothing
   if(changed == false)
       return ;

   else if(item->column()<=0)
         return;

   changed = true;
   int row = item->row();
   //QMessageBox::information(NULL,"aa",QString::number(row));
   int index = ui->tableWidget->item(row,0)->text().toInt();
   QString content = ui->tableWidget->item(row,1)->text();
   QDate date = ui->calendarWidget->selectedDate();
  // QMessageBox::information(NULL,"aa",content);
   ModifyToDoListInPackage(date,index,content);
}


/**************************************************************
  // data process, in order to transmission throung net
     the following functions is to transform the
  // package to byteArray and from byteArray to package
 ***********************************************************************/
QByteArray Calendar::PackageToByteArray(ToDoListPackage *package)
{
    //initialize the xmlDocument
    QDomDocument doc;
    QDomElement root = doc.createElement("Package");
    //dates records of package
    int sizePackage = package->toDoListContent.size();
    for(int i = 0; i < sizePackage; i++)
    {
        QDomElement date = doc.createElement("Date");

        doc.appendChild(root);
        root.appendChild(date);

        QString dateOfPackage = package->toDoListContent.at(i).date.toString("yyyy-MM-dd");
        date.setAttribute("date",dateOfPackage);
        //indexes records of date
        int sizeContent = package->toDoListContent.at(i).toDoListRecord.size();
        for (int j = 0; j < sizeContent; j++)
        {
            int indexOfPackage = package->toDoListContent.at(i).toDoListRecord.at(j).index;
            QString contentOfPackage = package->toDoListContent.at(i).toDoListRecord.at(j).content;
            QDomElement index = doc.createElement("Index");
            QDomElement content = doc.createElement("Content");
            date.appendChild(index);
            date.appendChild(content);
            QDomText indexNodeText= doc.createTextNode(QString::number(indexOfPackage));
            QDomText contentNodeText= doc.createTextNode(contentOfPackage);
            index.appendChild(indexNodeText);
            content.appendChild(contentNodeText);

        }

    }
    if(root.childNodes().count()>0)
    {

        return doc.toByteArray();
    }
    else
    {
        doc.clear();
        return doc.toByteArray();
    }

}

ToDoListPackage Calendar::ByteArrayToPackage(QByteArray byteArray)
{
    ToDoListPackage returnPackage;
    returnPackage.toDoListContent.clear();
    QDomDocument doc;
    doc.setContent(byteArray,false);
    QDomNodeList dateList = doc.elementsByTagName("Date");
    int dateSize = dateList.size();
    if (dateSize <= 0)
    {
        return returnPackage;
    }
    else
    {
        for (int i = 0; i < dateSize; i++)
        {
            QString dateString(QString::fromLocal8Bit(dateList.at(i).attributes().item(0).nodeValue().toStdString().c_str()));
            QDate recordDate = StringToDate(dateString);
            int recordSize = dateList.at(i).childNodes().size()/2;
            QDomElement recordIndex = dateList.at(i).firstChildElement("Index");
            QDomElement contentIndex = dateList.at(i).firstChildElement("Content");

            QList<ToDoListRecord> recordDay;
            int firstIndex = recordIndex.text().toInt();
            QString firstContent = QString::fromStdString(contentIndex.text().toStdString());
            ToDoListRecord recordToDo = {firstIndex, firstContent};
            recordDay.push_back(recordToDo);
            while(--recordSize)
            {
                recordIndex = recordIndex.nextSiblingElement("Index");
                contentIndex = contentIndex.nextSiblingElement("Content");
                recordDay.push_back(recordToDo);
            }

            ToDoListOfDay DayToDo = {recordDate,recordDay};
            returnPackage.toDoListContent.push_back(DayToDo);

        }

    }

    return returnPackage;

}

QDate Calendar::StringToDate(QString date)
{
    QStringList DateList = date.split('-');
    QDate returnDate (DateList.at(0).toInt(),
                      DateList.at(1).toInt(),
                      DateList.at(2).toInt());
    return returnDate;
}



//for the main widget difine if the user have saved the changes
void Calendar:: setChanged(bool value)
{
    changed = value;
}
bool Calendar:: getChanged()
{
    return changed;
}
